//
// Created by v on 19-6-11.
//

#include <sys/stat.h>
#include <unistd.h>

#include "CMConfigCpp.h"

CMConfigCpp::CMConfigCpp(const char *filename)
{
    m_filename = filename;
    m_reader   = m_builder.newCharReader();
    parseFromFile();
}

CMConfigCpp::~CMConfigCpp()
{
    if (m_reader)
    {
        delete m_reader;
    }
}

int CMConfigCpp::parseFromFile()
{
    struct stat st;
    int         ret = stat(m_filename.c_str(), &st);
    if (ret < 0)
    {
        return -1;
    }
    char *data = (char *)malloc(st.st_size);
    if (!data)
        return -2;
    FILE *f = fopen(m_filename.c_str(), "r");
    if (f)
    {
        ret = fread(data, 1, st.st_size, f);
        if (ret != st.st_size)
        {
            fclose(f);
            free(data);
            return -3;
        }
        std::string  s = data;
        Json::String errs;
        ret =
            m_reader->parse(s.c_str(), s.c_str() + s.length(), &m_root, &errs);
        if (ret)
        {
            m_valid = true;
        }
        fclose(f);
        free(data);
    }
    return 0;
}

int CMConfigCpp::parse(const std::string &str)
{
    m_root.clear();
    Json::String errs;
    int ret = m_reader->parse(str.c_str(), str.c_str() + str.length(), &m_root,
                              &errs);
    if (ret)
        m_valid = true;
    return ret ? 0 : -1;
}

int CMConfigCpp::toString(std::string &result)
{
    if (!m_valid)
        return -1;
    Json::StreamWriterBuilder builder;
    result = Json::writeString(builder, m_root);
    return 0;
}

int CMConfigCpp::getBool(const char *key, bool &result)
{
    if (!m_valid)
        return -1;
    Json::Value v = m_root[key];
    if (v.isBool())
    {
        result = v.asBool();
        return 0;
    }
    return -2;
}

int CMConfigCpp::getInt(const char *key, int &result)
{
    if (!m_valid)
        return -1;
    Json::Value v = m_root[key];
    if (v.isInt())
    {
        result = v.asInt();
        return 0;
    }
    return -2;
}

int CMConfigCpp::getString(const char *key, std::string &result)
{
    if (!m_valid)
        return -1;
    Json::Value v = m_root[key];
    if (v.isString())
    {
        result = v.asString();
        return 0;
    }
    return -2;
}

int CMConfigCpp::getObject(const char *key, Json::Value &result)
{
    if (!m_valid)
        return -1;
    Json::Value v = m_root[key];
    if (v.isObject())
    {
        result = v;
        return 0;
    }
    return -2;
}

int CMConfigCpp::getRoot(Json::Value &root)
{
    if (!m_valid)
        return -1;
    root = m_root;
    return 0;
}

int CMConfigCpp::writeFile()
{
    if (!m_valid)
        return -1;
    std::string v;
    int         ret = toString(v);
    if (ret < 0)
        return -2;
    FILE *f = fopen(m_filename.c_str(), "w");
    if (!f)
        return -3;
    ret = fwrite(v.c_str(), 1, v.length(), f);
    return ret == v.length() ? 0 : -4;
}
